/* File: load.c
 * Description: 程序开始运行时从文件中加载数据的函数
 * Header: load.h
 * Function: loadAdmin loadUser loadOrder loadFlight
 * */

#include <stdio.h>
#include <stdlib.h>

#include "load.h"
#include "../common/data_process.h"
#include "../common/format.h"

void loadAdmin(struct admin **head) {
    /* Detail: 用于从文件中加载管理员数据，使用struct admin **head是要改变head的值
     * Para: head::struct admin 管理员链表的头结点
     * */

    // 打开文件，将链表头设为空指针
    FILE *adminFile;
    adminFile = fopen(adminFilename, "r");
    *head = NULL;

    // 开始读取文件
    while (!feof(adminFile)) {
        struct admin *node = (struct admin *) malloc(sizeOfAdmin);
        // 这里再次判断是否督导文件尾部，保险
        if (fscanf(adminFile, adminFormat, node->account, node->password) == EOF) {
            node->next = NULL;
            break;
        } else {
            node->next = NULL;
            addToAdminHead(head, node);
        }
        // 先设置成空值在free掉，不然会出错
        node = NULL;
        free(node);
    }
    fclose(adminFile);
}

void loadUser(struct user **head) {
    /* Detail: 用于从文件中加载管理员数据，使用二重指针道理同上，且流程基本一样，不在赘述
     * Para: head::struct user 管理员链表的头结点
     * */
    FILE *userFile;
    userFile = fopen(userFilename, "r");
    *head = NULL;
    while (!feof(userFile)) {
        struct user *node = (struct user *) malloc(sizeOfUser);
        if (fscanf(userFile, userFormat, node->username, node->password, node->realName, node->telephone) == EOF) {
            node->next = NULL;
            break;
        } else {
            node->next = NULL;
            addToUserHead(head, node);
        }
        node = NULL;
        free(node);
    }
    fclose(userFile);
}

void loadFlight(struct flight **head) {
    /* Detail: 用于从文件中加载管理员数据，使用二重指针道理同上，且流程基本一样，不在赘述
     * Para: head::struct flight 管理员链表的头结点
     * */
    FILE *flightFile, *flightBookFile, *flightSeatFile;
    flightFile = fopen(flightFilename, "r");
    flightBookFile = fopen("flight_book.dat", "r");
    flightSeatFile = fopen("flight_seat.dat", "r");

    *head = NULL;

    while (!feof(flightFile)) {
        struct flight *node = (struct flight *) malloc(sizeOfFlight);
        if (fscanf(flightFile, flightFormat, node->number, node->position.departure_city,
                   node->position.destination_city, node->position.departure_airport,
                   node->position.destination_airport, &node->takeOffTime, &node->landTime, &node->seats,
                   &node->economyPrice, &node->firstToEconomy, &node->businessToEconomy,
                   &node->economyCutOff, &node->flightTripType) == EOF) {
            node->next = NULL;
            break;
        } else {
            int content;
            node->seatTypes = (flight_seat_type *) malloc(sizeof(flight_seat_type) * (node->seats + 1));
            node->bookTypes = (flight_book_type *) malloc(sizeof(flight_book_type) * (node->seats + 1));

            // 防止指针为空，不然之后会出异常，而且是CLion debug的时候出事，但是单独运行就没问题
            if (node->bookTypes == NULL || node->seatTypes == NULL) {
                continue;
            }

            // 一定要读取%1d，读取一位整数，不然就出事了，这里读为整数是为了保险，直接读出过bug
            for (int i = 0; i < node->seats; ++i) {
                fscanf(flightBookFile, "%1d", &content);
                if (content == BOOKED) {
                    node->bookTypes[i] = BOOKED;
                } else {
                    node->bookTypes[i] = UNBOOKED;
                }

                fscanf(flightSeatFile, "%1d", &content);
                if (content == FIRST_CLASS_CABIN) {
                    node->seatTypes[i] = FIRST_CLASS_CABIN;
                } else if (content == BUSINESS_CLASS_CABIN) {
                    node->seatTypes[i] = BUSINESS_CLASS_CABIN;
                } else {
                    node->seatTypes[i] = ECONOMY_CLASS_CABIN;
                }
            }
            node->next = NULL;
            addToFlightHead(head, node);
        }
        node = NULL;
        free(node);
    }

    fclose(flightFile);
    fclose(flightBookFile);
    fclose(flightSeatFile);
}

void loadOrder(struct order **head) {
    /* Detail: 用于从文件中加载管理员数据，使用二重指针道理同上，且流程基本一样，不在赘述
     * Para: head::struct order 管理员链表的头结点
     * */
    FILE *orderFile;
    orderFile = fopen(orderFilename, "r");
    *head = NULL;

    while (!feof(orderFile)) {
        struct order *node = (struct order *) malloc(sizeOfOrder);
        if (fscanf(orderFile, orderFormat, node->flightNumber, node->userName, &node->peopleType, &node->seat,
                   &node->isCheckIn, &node->airlineMeal, &node->overweight, &node->totalPrice) == EOF) {
            node->next = NULL;
            break;
        } else {
            node->next = NULL;
            addToOrderHead(head, node);
        }
        node = NULL;
        free(node);
    }
    fclose(orderFile);
}
